package com.xbang.core.hibernate.config;


import java.util.HashSet;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.cfg.AnnotationConfiguration;
import org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean;

import com.opensymphony.xwork2.util.ResolverUtil;

/**
 * @author dev.zhang
 * @author ahuaxuan(aaron zhang)
 * 
 * @since 2008-4-24
 */
public class PackageAnnotationSessionFactoryBean extends AnnotationSessionFactoryBean {

	private static final Log logger = LogFactory.getLog(PackageAnnotationSessionFactoryBean.class);
	
	private String[] annotatedEntityPackages;

	/**
     * @return the annotatedEntityPackages
     */
    public String[] getAnnotatedEntityPackages() {
        return annotatedEntityPackages;
    }
    
    /**
     * @param annotatedEntityPackages the annotatedEntityPackages to set
     */
    public void setAnnotatedEntityPackages(String[] annotatedEntityPackages) {
        this.annotatedEntityPackages = annotatedEntityPackages;
    }

	/* (non-Javadoc)
	 * @see org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean#postProcessAnnotationConfiguration(org.hibernate.cfg.AnnotationConfiguration)
	 */
	@Override
	@SuppressWarnings("unchecked")
	protected void postProcessAnnotationConfiguration(AnnotationConfiguration annotationConfiguration) throws HibernateException {
	    
	    Set<Class<?>> entityClasses = new HashSet<Class<?>>();
        
        if (annotatedEntityPackages != null) {
            try {

                if(logger.isDebugEnabled()) {
                    logger.debug("Trying to locate entityClasses in paths: " + annotatedEntityPackages);
                }
                
                // Try to locate all the entityClasses under entityPackages
                ResolverUtil<Object> resolver = new ResolverUtil<Object>();
                resolver.find(new ResolverUtil.Test() {
                    @SuppressWarnings("unchecked")
                    public boolean matches(Class type) {
                        return type.isAnnotationPresent(javax.persistence.Entity.class);
                    }
                }, annotatedEntityPackages);

                entityClasses = resolver.getClasses();

                // add all the entityClasses to configuration 
                if (entityClasses != null && !entityClasses.isEmpty()) {
                    
                    for(Class<?> entityClass : entityClasses) {
                        annotationConfiguration.addAnnotatedClass(entityClass);
                    }
                    
                } else {
                    logger.warn("Can not find any entityClasses in any paths : " + annotatedEntityPackages);
                }
            } catch (Exception e) {
                logger.error("Catch Exception when match the annotation class by package", e);
            }
        }

	}

}
